package edu.whut.mall.admin.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import edu.whut.mall.admin.dto.ShiroSysUser;
import edu.whut.mall.admin.mapper.AdminMapper;
import edu.whut.mall.admin.mapper.AdminRoleMapper;
import edu.whut.mall.admin.mapper.RoleMapper;
import edu.whut.mall.admin.model.Role;
import edu.whut.mall.admin.vo.AdminVo;
import edu.whut.mall.pojo.mapper.MerchantAdminMapper;
import edu.whut.mall.admin.model.Admin;
import edu.whut.mall.admin.model.AdminRole;
import edu.whut.mall.pojo.model.MerchantAdmin;
import edu.whut.mall.admin.dto.AdminDto;
import edu.whut.mall.admin.service.IAdminService;
import edu.whut.mall.admin.shiro.util.ShiroUtil;
import edu.whut.mall.admin.vo.LoginVo;
import edu.whut.mall.common.util.Md5Util;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;


/**
 * Author: smq
 * Unit: D9lab
 * Date: 2021-06-11 17.40
 */

@Service
@Slf4j
public class AdminServiceImpl implements IAdminService {

    @Resource
    private AdminMapper adminMapper;

    @Resource
    private AdminRoleMapper adminRoleMapper;

    @Resource
    private MerchantAdminMapper merchantAdminMapper;

    @Resource
    private RoleMapper roleMapper;


    @Override
    public LoginVo loginAdmin(String loginIp, String username, String password) {
        LoginVo loginVo = new LoginVo();
        UsernamePasswordToken token = new UsernamePasswordToken(username, password);
        try {
            SecurityUtils.getSubject().login(token);
            loginVo.setKey(0);
            loginVo.setVisitTime(new Date());
            loginVo.setUsername(username);
            Admin admin = adminMapper.selectById(ShiroUtil.getUserId());
            Admin newAdmin = new Admin();
            newAdmin.setId(admin.getId());
            newAdmin.setLastLoginIp(loginIp);
            newAdmin.setLastLoginTime(new Date());
            newAdmin.setLoginCount(admin.getLoginCount() + 1);
            adminMapper.updateById(newAdmin);
            loginVo.setToken(ShiroUtil.getSession().getId());
            loginVo.setAdminType(ShiroUtil.getAdminType());
            return loginVo;
        } catch (UnknownAccountException e) {
            loginVo.setKey(-1);
            return loginVo;
        } catch (IncorrectCredentialsException e) {
            loginVo.setKey(-2);
            return loginVo;
        }
    }

    @Override
    public Admin insertOneUser(String regIp, AdminDto adminDto) {
        Admin admin = new Admin();
        BeanUtil.copyProperties(adminDto, admin);
        admin.setPassword(Md5Util.encrypt(adminDto.getPassword()));
        admin.setRegIp(regIp);
        int result = adminMapper.insert(admin);
        AdminRole adminRole = AdminRole.builder()
                .adminId(admin.getId())
                .roleId(1)
                .isDeleted(0)
                .createTime(new Date())
                .build();
        int insert = adminRoleMapper.insert(adminRole);
        if (result >= 0) {
            if (insert >= 0) {
                return admin;
            }
        }
        return null;
    }



    /**
     * 给用户指定角色
     * @param userId
     * @param roleIdString
     * @return
     */
    @Override
    public List<AdminRole> assignRoleUser(Integer userId, String roleIdString) {
        clearRoleUser(userId);
        String[] roleIdStringArr = roleIdString.split(",");
        int[] roleIds = Arrays.stream(roleIdStringArr).mapToInt(Integer::parseInt).toArray();
        List<AdminRole> adminRoleList = new ArrayList<>(roleIds.length);
        Arrays.stream(roleIds).forEach(roleId -> {
            AdminRole adminRole = new AdminRole();
            adminRole.setAdminId(userId);
            adminRole.setRoleId(roleId);
            adminRole.setIsDeleted(0);
            adminRoleList.add(adminRole);
            adminRoleMapper.insert(adminRole);
        });
        return adminRoleList;
    }

    /**
     * 分配之前先清空角色
     *
     * @param adminId
     */
    private void clearRoleUser(Integer adminId) {
        LambdaQueryWrapper<MerchantAdmin> query = new LambdaQueryWrapper<>();
        query.eq(MerchantAdmin::getAdminId, adminId);
        int result = merchantAdminMapper.selectCount(query);
        if (result == 0) {
            LambdaQueryWrapper<AdminRole> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(AdminRole::getAdminId, adminId);
            adminRoleMapper.delete(queryWrapper);
        } else {
            merchantAdminMapper.delete(query);
            LambdaQueryWrapper<AdminRole> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(AdminRole::getAdminId, adminId);
            adminRoleMapper.delete(queryWrapper);
        }
    }

    @Override
    public AdminVo getItem(Integer id) {
        return adminMapper.getAdminById(id);
    }


    @Override
    public Integer updateAdmin(Integer id, AdminDto adminDto) {
        Admin admin = adminMapper.selectById(id);
        if(adminDto.getPassword().equals(admin.getPassword())){
            //与原加密密码相同的不需要修改
            adminDto.setPassword(null);
        }else{
            //与原加密密码不同的需要加密修改
            if(StrUtil.isEmpty(adminDto.getPassword())){
                adminDto.setPassword(null);
            }else{
                adminDto.setPassword(Md5Util.encrypt(adminDto.getPassword()));
            }
        }
        BeanUtil.copyProperties(adminDto, admin);
        // 也可以直接改变 adminDto的id，直接更新adminDto
        // adminDto.setId(id);
        return adminMapper.updateById(admin);
    }

    @Override
    public Integer deleteAdminById(Integer id) {
        return adminMapper.deleteById(id);
    }

    @Override
    public Integer updateStatus(Integer id, Integer status) {
        Admin admin = adminMapper.selectById(id);
        admin.setStatus(status);
        return adminMapper.updateById(admin);
    }

    @Override
    public List<Role> getRoleList(Integer id) {
        return roleMapper.getRoleListByAdminId(id);
    }
}
